home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / visulztn / saoimage / saoimage.lha / btnlib / label.c < prev    next >
C/C++ Source or Header  |  1990-04-20  |  17KB  |  462 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /*
  6.  * Module:    label.c (Make Label)
  7.  * Project:    PROS -- ROSAT RSDC
  8.  * Purpose:    Stencil a label icon onto a blank (or prepared) button bitmap
  9.  * Subroutines:    btn_StencilLabel()        returns: void
  10.  * Subroutines:    static btn_Stencil()        returns: void
  11.  * Subroutines:    static btn_StencilAlligned()    returns: void
  12.  * Xlib calls:    none
  13.  * Copyright:    1989 Smithsonian Astrophysical Observatory
  14.  *        You may do anything you like with this file except remove
  15.  *        this copyright.  The Smithsonian Astrophysical Observatory
  16.  *        makes no representations about the suitability of this
  17.  *        software for any purpose.  It is provided "as is" without
  18.  *        express or implied warranty.
  19.  * Modified:    {0} Michael VanHilst    initial version        18 March 1989
  20.  *        {n} <who> -- <does what> -- <when>
  21.  */
  22.  
  23. /* one byte bitmask for bits included at index and to the right */
  24. static unsigned char rmask[8] = { 0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80 };
  25.  
  26. /* one byte bitmask for bits included at index and to the left */
  27. static unsigned char lmask[8] = { 0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff };
  28.  
  29. /*
  30.  * Subroutine:    btn_StencilLabel
  31.  * Purpose:    Stencil src through msk onto dst
  32.  * Returns:    void
  33.  * Called by:    btn_AddLabel()
  34.  * Uses:    btn_Stencil() or btn_StencilAlligned() below
  35.  * Xlib calls:    none
  36.  * Pre-state:    dst bitmap already contains border pattern
  37.  * Post-state:    dst bitmap has label stenciled on
  38.  * Method:    Determine alignment parameters and call an appropriate
  39.  *        routine to do the stenciling.
  40.  * Note:    src and msk are assumed to be matching bitmaps.
  41.  * Note:    For each byte, bit 0 (0x01) appears on the left.
  42.  * Note:    For each byte, bit 7 (0x80) appears on the right.
  43.  */
  44. void btn_StencilLabel ( src, msk, dst, src_byte_width, dst_byte_width,
  45.                 src_x, src_y, dst_x, dst_y, width, height, inverse )
  46.      unsigned char *src;    /* i: ptr to first byte of pattern */
  47.      unsigned char *msk;    /* i: ptr to same byte as src, but in msk */
  48.      unsigned char *dst;    /* i: ptr to first byte of destination */
  49.      int src_byte_width;    /* i: width in bytes of the src bitmap */
  50.      int dst_byte_width;    /* i: width in bytes of the dst bitmap */
  51.      int src_x, src_y;        /* i: coords of start of stencil in src */
  52.      int dst_x, dst_y;        /* i: coords of start of stencil in dst */
  53.      int width;            /* i: width (cols) to stencil */
  54.      int height;        /* i: number of lines (rows) to stencil */
  55.      int inverse;        /* i: invert the bits for reverse video look */
  56. {
  57.   int byte_offset;        /* l: byte offset of 1st src byte */
  58.   int first_src_bit;        /* l: index of 1st src bit in 1st src byte */
  59.   int first_dst_bit;        /* l: index of 1st dst bit in 1st dst byte */
  60.   int last_src_bit;        /* l: index of last src bit in last src byte */
  61.   int last_dst_bit;        /* l: index of last dst bit in last dst byte */
  62.   int rshift;            /* l: shift to align 1st src byte with dst */
  63.   int lshift;            /* l: shift to align 2nt src byte with dst */
  64.   unsigned char *last_dst;    /* l: ptr to last byte used in first line */
  65.   int first_mask;        /* l: bit mask, with coded sign (see above) */
  66.   int last_mask;        /* l: bit mask, with coded sign (see above) */
  67.  
  68.   static void btn_Stencil(), btn_StencilInv();
  69.   static void btn_StencilAlligned(),btn_StencilAllignedInv();
  70.  
  71.   /* advance src and msk to their first used bytes */
  72.   byte_offset = (src_y * src_byte_width) + (src_x / 8);
  73.   src += byte_offset;
  74.   msk += byte_offset;
  75.   /* advance dst to its first used line */
  76.   dst += dst_y * dst_byte_width;
  77.   /* determine byte ptr to last used byte in first used dst row */
  78.   last_dst = dst + (dst_x + width - 1) / 8;
  79.   /* advance dst to its first used byte */
  80.   dst += dst_x / 8;
  81.   /* determine bit indexes of first and last bits in their bytes */
  82.   first_src_bit = src_x & 0x0007;
  83.   first_dst_bit = dst_x & 0x0007;
  84.   last_dst_bit = (dst_x + width - 1) & 0x0007;
  85.   last_src_bit = (src_x + width - 1) & 0x0007;
  86.   /* get appropriate mask for bits used in first dst byte */
  87.   first_mask = (int)rmask[first_dst_bit];
  88.   /* get appropriate mask and compensations for bits used in last dst byte */
  89.   if( dst == last_dst ) {
  90.     first_mask &= (int)lmask[last_dst_bit];
  91.     last_mask = 0;
  92.   } else if( last_dst_bit == 7 ) {
  93.     last_mask = 0;
  94.     ++last_dst;
  95.   } else {
  96.     last_mask = (int)lmask[last_dst_bit];
  97.   }
  98.   /* test bit alignment between dst and src */
  99.   if( first_src_bit == first_dst_bit ) {
  100.     /* call routine for perfect allignment stenciling */
  101.     if( inverse )
  102.       btn_StencilAllignedInv(src, msk, dst, last_dst, first_mask, last_mask,
  103.                  src_byte_width, dst_byte_width, height);
  104.     else
  105.       btn_StencilAlligned(src, msk, dst, last_dst, first_mask, last_mask,
  106.               src_byte_width, dst_byte_width, height);
  107.   } else {
  108.     /* determine rshift and lshift from bit offsets */
  109.     lshift = first_dst_bit - first_src_bit;
  110.     rshift = 8 - lshift;
  111.     /* encode handling of first and last bytes */
  112.     if( first_dst_bit > first_src_bit )
  113.       first_mask = -first_mask;
  114.     if( last_dst_bit < last_src_bit )
  115.       last_mask = -last_mask;
  116.     /* call routine for imperfect allignment stenciling */
  117.     if( inverse )
  118.       btn_StencilInv(src, msk, dst, last_dst, first_mask, last_mask,
  119.              rshift, lshift, src_byte_width, dst_byte_width, height);
  120.     else
  121.       btn_Stencil(src, msk, dst, last_dst, first_mask, last_mask,
  122.           rshift, lshift, src_byte_width, dst_byte_width, height);
  123.   }
  124. }
  125.  
  126. /*
  127.  * Subroutine:    btn_Stencil(Inv)
  128.  * Purpose:    Stencil src through msk onto dst with imperfect byte alignment.
  129.  * Parameters:    See argument declarations and note the following.
  130.  * Parameter:    first_mask: a one byte bitmask passed as an int
  131.  *        note: first_mask is negated if first_dst_bit > first_src_bit.
  132.  * Parameter:    last_mask: a one byte bitmask passed as an int
  133.  *        note: last_mask is negated if last_dst_bit < last_src_bit.
  134.  *        note: last_mask = 0 if there is no need to do a last byte.
  135.  * Returns:    void
  136.  * Called by:    btn_StencilLabel() above
  137.  * Xlib calls:    none
  138.  * Pre-state:    dst bitmap already contains border pattern
  139.  * Post-state:    dst bitmap has label stenciled on
  140.  * Exception:    Src and dst bytes must not allign (bit offsets must differ).
  141.  * Method:    Basic stencil operation is (dst & ^mask) | (src & mask).
  142.  *        Operation to make dst aligned byte from 2 src bytes is:
  143.  *         (src1 >> rshift) | (src2 << lshift).
  144.  *        Special masks are applied at beginning and end in case less
  145.  *        than a full byte is to be stenciled.  If no special masking
  146.  *        is needed for a last byte, last_dst covers it and last_mask=0;
  147.  * Note:    src and msk are assumed to be matching bitmaps.
  148.  * Note:    For each byte, bit 0 (0x01) appears on the left.
  149.  * Note:    For each byte, bit 7 (0x80) appears on the right.
  150.  * Note:    ~*s >> rshift does not work on SPARK and MIPS, use (0xff - *s)
  151.  */
  152. static void btn_Stencil ( src, msk, dst, last_dst, first_mask, last_mask,
  153.               rshift, lshift,
  154.               src_byte_width, dst_byte_width, height )
  155.      unsigned char *src;    /* i: ptr to first byte used of pattern */
  156.      unsigned char *msk;    /* i: ptr to same byte as src, but in msk */
  157.      unsigned char *dst;    /* i: ptr to first byte used of destination */
  158.      unsigned char *last_dst;    /* i: ptr to last byte used in first line */
  159.      int first_mask;        /* i: bit mask, with coded sign (see above) */
  160.      int last_mask;        /* i: bit mask, with coded sign (see above) */
  161.      int rshift;        /* i: shift to align 1st src byte with dst */
  162.      int lshift;        /* i: shift to align 2nt src byte with dst */
  163.      int src_byte_width;    /* i: width in bytes of the src bitmap */
  164.      int dst_byte_width;    /* i: width in bytes of the dst bitmap */
  165.      int height;        /* i: number of line (rows) to stencil */
  166. {
  167.   unsigned char mask, val;    /* l: composite mask and source val */
  168.   register unsigned char *s, *m, *d;
  169.   unsigned char ff = 0xff;        /* -1 for ~ operation */
  170.  
  171.   /* loop and decrement height as a row counter */
  172.   while( --height >= 0 ) {
  173.     s = src;
  174.     m = msk;
  175.     d = dst;
  176.     /* handle the first (maybe partial) dst byte */
  177.     if( first_mask < 0 ) {
  178.       mask = (*m << lshift) & (unsigned char)(-first_mask);
  179.       *d = (*d & (ff - mask)) | ((*s << lshift) & mask);
  180.     } else {
  181.       mask = (*m >> rshift);
  182.       m++;
  183.       mask |= (*m << lshift);
  184.       mask &= (unsigned char)first_mask;
  185.       val = (*s >> rshift);
  186.       s++;
  187.       val |= (*s << lshift);
  188.       *d = (*d & (ff - mask)) | (val & mask);
  189.     }
  190.     /* handle middle (full) dst bytes */
  191.     while( ++d < last_dst ) {
  192.       mask = (*m >> rshift);
  193.       m++;
  194.       mask |= (*m << lshift);
  195.       val = (*s >> rshift);
  196.       s++;
  197.       val |= (*s << lshift);
  198.       *d = (*d & (ff - mask)) | (val & mask);
  199.     }
  200.     /* handle last (maybe partial) dst byte */
  201.     if( last_mask < 0 ) {
  202.       mask = (*m >> rshift) & (unsigned char)(-last_mask);
  203.       *d = (*d & (ff - mask)) | ((*s >> rshift) & mask);
  204.     } else if( last_mask > 0 ) {
  205.       mask = (*m >> rshift);
  206.       m++;
  207.       mask |= (*m << lshift);
  208.       mask &= (unsigned char)last_mask;
  209.       val = (*s >> rshift);
  210.       s++;
  211.       val |= (*s << lshift);
  212.       *d = (*d & (ff - mask)) | (val & mask);
  213.     }
  214.     /* advance to next line */
  215.     src += src_byte_width;
  216.     msk += src_byte_width;
  217.     dst += dst_byte_width;
  218.     last_dst += dst_byte_width;
  219.   }
  220. }
  221. static void btn_StencilInv ( src, msk, dst, last_dst, first_mask, last_mask,
  222.                  rshift, lshift,
  223.                  src_byte_width, dst_byte_width, height )
  224.      unsigned char *src;    /* i: ptr to first byte used of pattern */
  225.      unsigned char *msk;    /* i: ptr to same byte as src, but in msk */
  226.      unsigned char *dst;    /* i: ptr to first byte used of destination */
  227.      unsigned char *last_dst;    /* i: ptr to last byte used in first line */
  228.      int first_mask;        /* i: bit mask, with coded sign (see above) */
  229.      int last_mask;        /* i: bit mask, with coded sign (see above) */
  230.      int rshift;        /* i: shift to align 1st src byte with dst */
  231.      int lshift;        /* i: shift to align 2nt src byte with dst */
  232.      int src_byte_width;    /* i: width in bytes of the src bitmap */
  233.      int dst_byte_width;    /* i: width in bytes of the dst bitmap */
  234.      int height;        /* i: number of line (rows) to stencil */
  235. {
  236.   unsigned char mask, val;    /* l: composite mask and source val */
  237.   register unsigned char *s, *m, *d;
  238.   unsigned char ff = 0xff;        /* -1 for ~ operation */
  239.  
  240.   /* loop and decrement height as a row counter */
  241.   while( --height >= 0 ) {
  242.     s = src;
  243.     m = msk;
  244.     d = dst;
  245.     /* handle the first (maybe partial) dst byte */
  246.     if( first_mask < 0 ) {
  247.       mask = (*m << lshift) & (unsigned char)(-first_mask);
  248.       *d = (*d & (ff - mask)) | (((ff - *s) << lshift) & mask);
  249.     } else {
  250.       mask = (*m >> rshift);
  251.       m++;
  252.       mask |= (*m << lshift);
  253.       mask &= (unsigned char)first_mask;
  254.       val = ((ff - *s) >> rshift);
  255.       s++;
  256.       val |= ((ff - *s) << lshift);
  257.       *d = (*d & (ff - mask)) | (val & mask);
  258.     }
  259.     /* handle middle (full) dst bytes */
  260.     while( ++d < last_dst ) {
  261.       mask = (*m >> rshift);
  262.       m++;
  263.       mask |= (*m << lshift);
  264.       val = ((ff - *s) >> rshift);
  265.       s++;
  266.       val |= ((ff - *s) << lshift);
  267.       *d = (*d & (ff - mask)) | (val & mask);
  268.     }
  269.     /* handle last (maybe partial) dst byte */
  270.     if( last_mask < 0 ) {
  271.       mask = (*m >> rshift) & (unsigned char)(-last_mask);
  272.       *d = (*d & (ff - mask)) | (((ff - *s) >> rshift) & mask);
  273.     } else if( last_mask > 0 ) {
  274.       mask = (*m >> rshift);
  275.       m++;
  276.       mask |= (*m << lshift);
  277.       mask &= (unsigned char)last_mask;
  278.       val = ((ff - *s) >> rshift);
  279.       s++;
  280.       val |= ((ff - *s) << lshift);
  281.       *d = (*d & (ff - mask)) | (val & mask);
  282.     }
  283.     /* advance to next line */
  284.     src += src_byte_width;
  285.     msk += src_byte_width;
  286.     dst += dst_byte_width;
  287.     last_dst += dst_byte_width;
  288.   }
  289. }
  290.  
  291. /*
  292.  * Subroutine:    btn_StencilAlligned(Inv)
  293.  * Purpose:    Stencil src through msk onto dst with perfect byte alignment.
  294.  * Returns:    void
  295.  * Called by:    btn_StencilLabel() above
  296.  * Xlib calls:    none
  297.  * Pre-state:    dst bitmap already contains border pattern
  298.  * Post-state:    dst bitmap has label stenciled on
  299.  * Exception:    Src and dst bytes must allign (bit for bit).
  300.  * Method:    Basic stencil operation is (dst & ~mask) | (src & mask).
  301.  *        Special masks are applied at beginning and end in case less
  302.  *        than a full byte is to be stenciled.  If no special masking
  303.  *        is needed for a last byte, last_dst covers it and last_mask=0;
  304.  * Note:    src and msk are assumed to be matching bitmaps.
  305.  * Note:    For each byte, bit 0 (0x01) appears on the left.
  306.  * Note:    For each byte, bit 7 (0x80) appears on the right.
  307.  * Note:    ~*s >> rshift does not work on SPARK and MIPS, use (0xff - *s)
  308.  */
  309. static void btn_StencilAlligned ( src, msk, dst, last_dst, first_mask,
  310.                   last_mask, src_byte_width, dst_byte_width,
  311.                   height, inverse )
  312.      unsigned char *src;    /* i: ptr to first byte used of pattern */
  313.      unsigned char *msk;    /* i: ptr to same byte as src, but in msk */
  314.      unsigned char *dst;    /* i: ptr to first byte used of destination */
  315.      unsigned char *last_dst;    /* i: ptr to last byte used in first line */
  316.      int first_mask;        /* i: bit mask, with coded sign (see above) */
  317.      int last_mask;        /* i: bit mask, with coded sign (see above) */
  318.      int src_byte_width;    /* i: width in bytes of the src bitmap */
  319.      int dst_byte_width;    /* i: width in bytes of the dst bitmap */
  320.      int height;        /* i: number of line (rows) to stencil */
  321. {
  322.   unsigned char mask;        /* l: composite mask for use on end bytes */
  323.   register unsigned char *s, *m, *d;
  324.   unsigned char ff = 0xff;        /* -1 for ~ operation */
  325.  
  326.   /* loop and decrement height as a row counter */
  327.   while( --height >= 0 ) {
  328.     s = src;
  329.     m = msk;
  330.     d = dst;
  331.     /* do first byte, use mask in case it is not a full byte */
  332.     mask = (unsigned char)first_mask & *m;
  333.     *d = (*d & (ff - mask)) | (*s & mask);
  334.     /* do middle (full) bytes */
  335.     while( ++d < last_dst ) {
  336.       ++m;
  337.       ++s;
  338.       *d = (*d & (ff - *m)) | (*s & *m);
  339.     }
  340.     /* if there is a partial last byte, do it */
  341.     if( last_mask ) {
  342.       ++m;
  343.       mask = (unsigned char)last_mask & *m;
  344.       ++s;
  345.       *d = (*d & (ff - mask)) | (*s & mask);
  346.     }
  347.     /* advance to next line */
  348.     src += src_byte_width;
  349.     msk += src_byte_width;
  350.     dst += dst_byte_width;
  351.     last_dst += dst_byte_width;
  352.   }
  353. }
  354. static void btn_StencilAllignedInv ( src, msk, dst, last_dst, first_mask,
  355.                     last_mask, src_byte_width, dst_byte_width,
  356.                     height, inverse )
  357.      unsigned char *src;    /* i: ptr to first byte used of pattern */
  358.      unsigned char *msk;    /* i: ptr to same byte as src, but in msk */
  359.      unsigned char *dst;    /* i: ptr to first byte used of destination */
  360.      unsigned char *last_dst;    /* i: ptr to last byte used in first line */
  361.      int first_mask;        /* i: bit mask, with coded sign (see above) */
  362.      int last_mask;        /* i: bit mask, with coded sign (see above) */
  363.      int src_byte_width;    /* i: width in bytes of the src bitmap */
  364.      int dst_byte_width;    /* i: width in bytes of the dst bitmap */
  365.      int height;        /* i: number of line (rows) to stencil */
  366. {
  367.   unsigned char mask;        /* l: composite mask for use on end bytes */
  368.   register unsigned char *s, *m, *d;
  369.   unsigned char ff = 0xff;        /* -1 for ~ operation */
  370.  
  371.   /* loop and decrement height as a row counter */
  372.   while( --height >= 0 ) {
  373.     s = src;
  374.     m = msk;
  375.     d = dst;
  376.     /* do first byte, use mask in case it is not a full byte */
  377.     mask = (unsigned char)first_mask & *m;
  378.     *d = (*d & (ff - mask)) | ((ff - *s) & mask);
  379.     /* do middle (full) bytes */
  380.     while( ++d < last_dst ) {
  381.       ++m;
  382.       ++s;
  383.       *d = (*d & (ff - *m)) | ((ff - *s) & *m);
  384.     }
  385.     /* if there is a partial last byte, do it */
  386.     if( last_mask ) {
  387.       ++m;
  388.       mask = (unsigned char)last_mask & *m;
  389.       ++s;
  390.       *d = (*d & (ff - mask)) | ((ff - *s) & mask);
  391.     }
  392.     /* advance to next line */
  393.     src += src_byte_width;
  394.     msk += src_byte_width;
  395.     dst += dst_byte_width;
  396.     last_dst += dst_byte_width;
  397.   }
  398. }
  399.  
  400. #ifdef DEBUG
  401. pchar ( buf, wid, ht )
  402.      char *buf;
  403.      int wid, ht;
  404. {
  405.   int i, j;
  406.   (void)printf("\n");
  407.   for( i=0; i<ht; i++ ) {
  408.     for( j=0; j<wid; j++ ) {
  409.       (void)printf(" %4x", (unsigned char)buf[(i*wid)+j]);
  410.     }
  411.     (void)printf("\n");
  412.   }
  413. }
  414. bchar ( buf, wid, ht )
  415.      char *buf;
  416.      int wid, ht;
  417. {
  418.   int i, j, k, val;
  419.   (void)printf("\n");
  420.   for( i=0; i<ht; i++ ) {
  421.     for( j=0; j<wid; j++ ) {
  422.       k = 0;
  423.       val = (unsigned int)buf[(i*wid)+j];
  424.       if( val & 1 )   k += 10000000;
  425.       if( val & 2 )   k += 1000000;
  426.       if( val & 4 )   k += 100000;
  427.       if( val & 8 )   k += 10000;
  428.       if( val & 16 )  k += 1000;
  429.       if( val & 32 )  k += 100;
  430.       if( val & 64 )  k += 10;
  431.       if( val & 128 ) k += 1;
  432.       (void)printf("%08d", k);
  433.     }
  434.     (void)printf("\n");
  435.   }
  436. }
  437. dchar ( buf, wid, ht )
  438.      char *buf;
  439.      int wid, ht;
  440. {
  441.   int i, j, k, val;
  442.   char foo[10];
  443.   (void)printf("\n");
  444.   for( i=0; i<ht; i++ ) {
  445.     for( j=0; j<wid; j++ ) {
  446.       strcpy(foo, "........");
  447.       val = (unsigned int)buf[(i*wid)+j];
  448.       if( val & 1 ) foo[0] = 'O';
  449.       if( val & 2 ) foo[1] = 'O';
  450.       if( val & 4 ) foo[2] = 'O';
  451.       if( val & 8 ) foo[3] = 'O';
  452.       if( val & 16 ) foo[4] = 'O';
  453.       if( val & 32 ) foo[5] = 'O';
  454.       if( val & 64 ) foo[6] = 'O';
  455.       if( val & 128 ) foo[7] = 'O';
  456.       (void)printf("%8s", foo);
  457.     }
  458.     (void)printf("\n");
  459.   }
  460. }
  461. #endif
  462.